package main

import (
	"context"
	"fmt"
	"time"
)

//context:更优雅的方式实现关闭协程的功能。也就是说，实现和上例一样，同时关闭多个协程的功能。

func monitor(ctx context.Context, number int) {
	for { //无限循环
		select {
		// 检查 ctx.Done() 是否可读，可读就说明该 context 已经取消
		case <-ctx.Done():
			fmt.Printf("监控器%v，监控结束。\n", number)
			return
		default:
			fmt.Printf("监控器%v，正在监控中...\n", number)
			time.Sleep(1 * time.Second)
		}
	}
}

func main() {
	//创建context ，必须传入的参数是父级context
	ctx, cancel123 := context.WithCancel(context.Background())

	//运行了5个协程，这5个协程，都同接收了同一个context作为参数
	for i := 1; i <= 5; i++ {
		go monitor(ctx, i)
	}

	time.Sleep(5 * time.Second) //为了这协程有机会执行

	// 关闭所有 goroutine,这个方法名，就是在创建context的时候，返回的第二个值
	cancel123()
	fmt.Println("context 已取消")

	// 等待5s，若此时屏幕没有输出 <正在监控中> 就说明所有的goroutine都已经关闭
	time.Sleep(5 * time.Second)

	fmt.Println("主程序退出！！")

}
